import 'dart:async';

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

/// InkWell with debounce , default delay 1s
class DebounceInkWell extends StatelessWidget {
  final Widget child;
  final GestureTapCallback? onTap;
  final Duration delay;
  final BorderRadius? borderRadius;

  const DebounceInkWell({
    super.key,
    required this.child,
    this.onTap,
    this.borderRadius,
    this.delay = const Duration(seconds: 1),
  });

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => DebounceController(delay),
      child: Consumer<DebounceController>(
        builder: (context, controller, widget) => InkWell(
          onTap: controller.debounce(onTap),
          borderRadius: borderRadius,
          child: child,
        ),
      ),
    );
  }
}

/// GestureDetector with debounce , default delay 1s
class DebounceGestureDetector extends StatelessWidget {
  final Widget child;
  final GestureTapCallback? onTap;
  final Duration delay;

  const DebounceGestureDetector({
    Key? key,
    required this.child,
    this.onTap,
    this.delay = const Duration(seconds: 1),
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => DebounceController(delay),
      child: Consumer<DebounceController>(
        builder: (context, controller, widget) => GestureDetector(
          onTap: controller.debounce(onTap),
          child: child,
        ),
      ),
    );
  }
}

class DebounceController with ChangeNotifier {
  Timer? _timer;
  bool _enable = true;
  final Duration delay;

  DebounceController(this.delay);

  /// [function] 要执行的方法
  /// [delay] 要迟延的时长
  GestureTapCallback? debounce(
    GestureTapCallback? function, {
    Duration? delay,
  }) {
    if (function == null) return null;
    void target() {
      if (_enable) {
        _enable = false;
        function.call();
        _timer = Timer(delay ?? this.delay, () {
          _enable = true;
        });
      }
    }

    return target;
  }

  @override
  void dispose() {
    _timer?.cancel();
    _enable = true;
    super.dispose();
  }
}
